﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ComponentModel;

namespace WebPALTT.Lib
{
    /// <summary>
    /// A Folder Action containing a list of other actions.
    /// </summary>
    [Serializable]
    public class ActionItem_Folder : ActionItem
    {
        /// <summary>
        /// Static method containing the CustomType of this action for comparison.
        /// </summary>
        public static string Type { get { return "Folder"; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public override ActionType ActionType { get { return ActionType.Action; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public override string CustomType { get { return ActionItem_Folder.Type; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public override System.Drawing.Image Icon { get { return global::WebPALTT.Lib.Icons.folder; } }
        [BrowsableAttribute(false)]
        public override bool HasChildren { get { return mActions.Count > 0; } }
        [BrowsableAttribute(false)]
        public override bool CanAddChildren { get { return true; } }
        public override string[] DataHeaders { get { return new string[] { }; } }
        public override string[] DataHeaders_Save { get { return new string[] { }; } }

        public override ExecutionStatus ExecutionStatus { get { return base.mExecutionStatus; } }

        ActionItemCollection mActions;

        public ActionItem_Folder() : this("") { }

        public ActionItem_Folder(string name) : this(name, null) { }

        public ActionItem_Folder(string name, ActionItemCollection actions)
            : base(name)
        {
            if (actions != null)
                mActions = actions;
            else
                mActions = new ActionItemCollection();
        }

        public ActionItem_Folder(SerializationInfo info, StreamingContext ctxt)
            : base(info, ctxt)
        {
            mActions = (ActionItemCollection)info.GetValue("Actions", typeof(ActionItemCollection));
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            base.GetObjectData(info, ctxt);
            info.AddValue("Actions", mActions);
        }

        public override string[] Validate()
        {
            List<string> errors = new List<string> { };
            if (Children.Count == 0)
                errors.Add("Warning: action[" + Name + "(" + ActionType + ")]. - Folder doesn't contain any sub actions");

            foreach (ActionItem action in Children)
                errors.AddRange(action.Validate());

            return errors.ToArray();
        }

        public override void SetParent(ActionItem parent, int index = 0)
        {
            base.SetParent(parent, index);
            for (int i = 0; i < mActions.Count; i++)
                mActions[i].SetParent(this, i);
        }

        public override ActionItem FindChild(Guid key)
        {
            return mActions.Find(
                delegate(ActionItem item)
                {
                    if(Guid.Equals(item.Key, key))
                        return true;
                    return false;
                }, true);
        }

        public override ActionItem[] FindChildren(Guid key)
        {
            List<ActionItem> list = new List<ActionItem> { };
            list.AddRange(mActions.FindAll(
                delegate(ActionItem item)
                {
                    if (Guid.Equals(item.Key, key))
                        return true;
                    return false;
                }, true));
            return list.ToArray();
        }

        public override ActionItemCollection Children
        {
            get { return mActions; }
        }

        public override Dictionary<string, object> Execute(Scenario scenario, ScenarioResults resultScene, Type scriptType, object scriptObj) 
        {
            if (base.mExecutionStatus == Lib.ExecutionStatus.RunChildren) // Has already been run
            {
                base.mExecutionStatus = Lib.ExecutionStatus.Complete;
                return null;
            }
            else if (this.HasChildren)
            {
                base.mExecutionStatus = Lib.ExecutionStatus.RunChildren;
                return new Dictionary<string, object>();
            }
            else
            {
                base.mExecutionStatus = Lib.ExecutionStatus.Complete;
                return new Dictionary<string, object>();
            }

        }
    }
}
